#include "GY_ContainerTransform.h"
#include <QPainter>
#include <QDebug>
#include "Graphics/GY_GraphicsReflection.h"

GY_ContainerTransform::GY_ContainerTransform(const QString &guid, QGraphicsItem *pItem, QGraphicsItem *parent)
    :GY_Object(guid),QGraphicsItemGroup(parent)
{
    //设置基类GY_Object的对象
    setpItem(pItem);
    //标记数据，key=CenterPointF(2)表示中心点位置
    GY_Object::setUserData(GY_ENUM::CenterPointF,QVariant::fromValue(centerPointF));
    //this是原版item
    GY_Object::setUserData(GY_ENUM::IsCopy,QVariant::fromValue(0));
    //对象类型
    GY_Object::setUserData(GY_ENUM::ObjectType,QVariant::fromValue(1));
    m_pItem->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsScenePositionChanges);
    m_pItem->setAcceptHoverEvents(true);
    this->setHandlesChildEvents(false);
}

//bool GY_ContainerTransform::updateObjectName(const QString &name, const QVariant &value)
//{
//    if(!value.canConvert<QString>())
//        return false;
//    m_PropertyInfoMap[name].propertyValue = value;
//    return true;
//}

//bool GY_ContainerTransform::addItem(QGraphicsItem *pItem)
//{
//     QVariant data=pItem->data(GY_ENUM::ObjectType);
//    if(!pItem->data(GY_ENUM::ObjectType).isValid())
//    {
//        return false;
//    }
//    else if(pItem->data(GY_ENUM::ObjectType)==0)
//    {
//        m_ChildrensMap.insert(((GY_BasicsGraphicsObject*)pItem)->getGuid(),(GY_BasicsGraphicsObject*)pItem);
//    }
//    else if(pItem->data(GY_ENUM::ObjectType)==1)
//    {
//        m_ChildrensMap.insert(((GY_ContainerTransform*)pItem)->getGuid(),(GY_ContainerTransform*)pItem);
//    }
//    this->addToGroup(pItem);
//    setContainerEditPointF();
////    qDebug()<< this->getGuid() << ((GY_BasicsGraphicsObject*)pItem)->getGuid() <<  "***" << this->boundingRect().width()<< this->boundingRect().height();
//    return true;
//}
bool GY_ContainerTransform::addItem(GY_Object *pItem)
{
    if(pItem->inherits("GY_BasicsGraphicsObject"))
    {
        this->addToGroup((GY_BasicsGraphicsObject*)pItem);
    }
    else if(pItem->inherits("GY_ContainerTransform"))
    {
        this->addToGroup((GY_ContainerTransform*)pItem);
    }
//    else if(pItem->inherits("GY_BasicsDataObjects"))
//    {
//        this->addToGroup((GY_BasicsDataObjects*)pItem);
//        QString str = pItem->getObjName();
//    }
//    else
//    {
//        return false;
//    }
    m_ChildrensMap.insert(pItem->getGuid(),pItem);
    m_OrderChildrens.append(pItem);
    setContainerEditPointF();
    return true;
}
/**
 * @brief removItem 移出组控件
 * @param 图形guid
 * @return 是否移除成功
 */
bool GY_ContainerTransform::removItem(const QString &guid)
{
    if(!m_ChildrensMap.contains(guid))
    {
        return false;
    }
    m_ChildrensMap.remove(guid);
    return true;
}
/**
 * @brief removItem 移出组控件
 * @param pItem 图形
 * @return 是否移除成功
 */
bool GY_ContainerTransform::removItem(const GY_Object *pItem)
{
    if(pItem->inherits("GY_BasicsGraphicsObject"))
    {
        this->removeFromGroup((GY_BasicsGraphicsObject*)pItem);
    }
    else if(pItem->inherits("GY_ContainerTransform"))
    {
        this->removeFromGroup((GY_ContainerTransform*)pItem);
    }
//    else if(pItem->inherits("GY_BasicsDataObjects"))
//    {
//        this->removeFromGroup((GY_BasicsDataObjects*)pItem);
//    }
    else
    {
//        return false;
    }
    if(m_OrderChildrens.contains((GY_Object *)pItem)) {
        m_OrderChildrens.removeOne((GY_Object *)pItem);
    }
    return  removItem(pItem->getGuid());
}
/**
 * @brief setChildProperty  设置子图形属性
 * @param guid 子图形GUID
 * @param propertyName 属性名称
 * @param value 属性值
 * @return
 */
bool GY_ContainerTransform::setChildProperty(const QString &guid, const QString &propertyName, const QVariant &value)
{
    if(m_ChildrensMap.contains(guid))
    {
        if(value.canConvert<QPointF>())
        {
            m_ChildrensMap[guid]->updateProperty(propertyName,value.toPointF()+getScenePosition());
//            qDebug() <<this->getGuid()<< guid<<  "------"<<  propertyName << value.toPointF() << getScenePosition();
        }
        else
        {
             m_ChildrensMap[guid]->updateProperty(propertyName,value);
        }
    }
    else
    {
        foreach (GY_Object* pObject, m_ChildrensMap)
        {
            if(pObject->inherits("GY_ContainerTransform"))
            {
                if(((GY_ContainerTransform*)pObject)->getIsContain(guid))
                {
                    ((GY_ContainerTransform*)pObject)->setChildProperty(guid,propertyName,value);
                    return true;
                }
            }
        }
    }
    return false;
}
/**
 * @brief getScenePosition 获取场景位置
 * @return 场景位置
 */
QPointF GY_ContainerTransform::getScenePosition()
{
    QPointF scenePosition = this->pos();
    if(m_PropertyInfoMap.contains("Position")&&m_PropertyInfoMap["Position"].propertyValue.canConvert<QPointF>())
    {
        scenePosition+=m_PropertyInfoMap["Position"].propertyValue.toPointF();
    }
    else if(m_PropertyInfoMap.contains("Point1")&&m_PropertyInfoMap.contains("Point2")
            &&m_PropertyInfoMap["Point1"].propertyValue.canConvert<QPointF>()&&m_PropertyInfoMap["Point2"].propertyValue.canConvert<QPointF>())
    {
        QPointF point1=m_PropertyInfoMap["Point1"].propertyValue.toPointF();
        QPointF point2=m_PropertyInfoMap["Point2"].propertyValue.toPointF();
        scenePosition+=QPointF(point2.x()-point1.x(),point2.y()-point1.y());
    }
//    qDebug() << this->getGuid()<< "------"<<  scenePosition;
    QGraphicsItem* pParentItem=this->parentItem();
    if(pParentItem!=nullptr&&pParentItem->data(GY_ENUM::ObjectType)==1)
    {
        scenePosition+=((GY_ContainerTransform*)pParentItem)->getScenePosition();
    }

    return scenePosition;
}

QMap<QString, GY_Object *> GY_ContainerTransform::getChildrensMap()
{
    return m_ChildrensMap;
}

void GY_ContainerTransform::setChildObjName(const QString &index)
{
    for(const auto& key : m_ChildrensMap.keys()) {
//        qDebug()<<m_ChildrensMap.value(key)->getObjName();
        m_ChildrensMap.value(key)->setObjName(m_ChildrensMap.value(key)->getObjName()+index);
        if(m_ChildrensMap.value(key)->getUserData(GY_ENUM::ObjectType) == 1) {
            ((GY_ContainerTransform*)m_ChildrensMap.value(key))->setChildObjName(index);
        }
    }
}

void GY_ContainerTransform::setTapeCircularChildObjName(const QString &index)
{
    for(const auto& key : m_ChildrensMap.keys()) {
        QString name = m_ChildrensMap.value(key)->getObjName();
        int ind = name.indexOf("_+_=_");
        if(ind != -1) {
            name.insert(ind,index);
        }
//        qDebug()<<name<<"name";
        m_ChildrensMap.value(key)->setObjName(name);
        if(m_ChildrensMap.value(key)->getUserData(GY_ENUM::ObjectType) == 1) {
            ((GY_ContainerTransform*)m_ChildrensMap.value(key))->setChildObjName(index);
        }
    }
}

void GY_ContainerTransform::setChildRepeatNum(const int &num)
{
    for(const auto& key : m_ChildrensMap.keys()) {
        m_ChildrensMap.value(key)->setRepeatNum(num);
        if(m_ChildrensMap.value(key)->getUserData(GY_ENUM::ObjectType) == 1) {
            ((GY_ContainerTransform*)m_ChildrensMap.value(key))->setChildRepeatNum(num);
        }
    }
}

QPainterPath GY_ContainerTransform::getPath()
{
    //分两种情况容器和item
    QPainterPath path;
    QMap<QString,GY_Object*>::Iterator iter = m_ChildrensMap.begin();
    while (iter != m_ChildrensMap.end()) {
        if(iter.value()->inherits("GY_BasicsGraphicsObject"))
        {
            path += ((GY_BasicsGraphicsObject*)iter.value())->shape();
        }
        else if(iter.value()->inherits("GY_ContainerTransform"))
        {
            path += ((GY_ContainerTransform*)iter.value())->getPath();
        }
        ++iter;
    }
    return path;
}

GY_Object *GY_ContainerTransform::copyItem(const QString &guid)
{
    if(getUserData(GY_ENUM::IsCopy) == 1) {
        GY_Object *tmp;
        this->copyItemSig(&tmp);
        //更新copyItem属性列表
        QMap<QString,GY_PropertyInfo>::Iterator iterProperty = m_PropertyInfoMap.begin();
        while (iterProperty != m_PropertyInfoMap.end()) {
            if(((iterProperty.value().updateType)&PointOfRelative) == PointOfRelative) {
                tmp->updateProperty(iterProperty.key(), submittingPropertyValues(iterProperty.value().updateType,iterProperty.value().propertyValue,this));
            }else if(((iterProperty.value().updateType)&NotUpdate) == NotUpdate){
                ++iterProperty;
                continue;
            }else {
                tmp->updateProperty(iterProperty.key(), iterProperty.value().propertyValue);
            }
            ++iterProperty;
        }
        return tmp;
    }
    GY_Object* pObj;
    if(guid.isEmpty()) {
        pObj = (GY_Object*)GY_GraphicsReflection::getInstance()->newInstanceObjectClass(this->metaObject()->className(),this->getGuid()+"-"+QString::number(m_MyGuid));
        m_MyGuid++;
    }else {
        pObj = (GY_Object*)GY_GraphicsReflection::getInstance()->newInstanceObjectClass(this->metaObject()->className(),guid);
    }
    if(pObj == nullptr) {
        qDebug()<<this->getGuid()<<"isEmpty";
        return nullptr;
    }
    QVector<GY_Object *> childrens = this->getOrderChildrens();
    int childrensSize = childrens.size();
    for(int i=0;i<childrensSize;i++) {
        ((GY_ContainerTransform*)pObj)->addItem(childrens[i]->copyItem());
    }

    QMap<QString,GY_PropertyInfo>::Iterator iterProperty = m_PropertyInfoMap.begin();
    while (iterProperty != m_PropertyInfoMap.end()) {
        if(((iterProperty.value().updateType)&PointOfRelative) == PointOfRelative) {
            pObj->updateProperty(iterProperty.key(), submittingPropertyValues(iterProperty.value().updateType,iterProperty.value().propertyValue,this));
        }else if(((iterProperty.value().updateType)&NotUpdate) == NotUpdate){
            ++iterProperty;
            continue;
        }else {
            pObj->updateProperty(iterProperty.key(), iterProperty.value().propertyValue);
        }
        ++iterProperty;
    }
    connect(pObj,&GY_Object::copyItemSig,this,&GY_Object::originalVersion);
    pObj->setUserData(GY_ENUM::IsCopy, QVariant::fromValue(1));
    return pObj;
}

QVector<GY_Object *> GY_ContainerTransform::getOrderChildrens()
{
    return m_OrderChildrens;
}

bool GY_ContainerTransform::setRotationCenter(const QPointF &val)
{
    if(!m_isRotation){
        return false;
    }
    m_rotationCenter = QPointF(-val.x(),-val.y());
    setCenterPointF(val);
    setContainerTransform();
    return true;
}

bool GY_ContainerTransform::isRotation() const
{
    return m_isRotation;
}

void GY_ContainerTransform::setIsRotation(bool isRotation)
{
    m_isRotation = isRotation;
}

qreal GY_ContainerTransform::scaleX() const
{
    return m_scaleX;
}

void GY_ContainerTransform::setScaleX(const qreal &scaleX)
{
    m_scaleX = scaleX;
    setContainerTransform();
}

qreal GY_ContainerTransform::scaleY() const
{
    return m_scaleY;
}

void GY_ContainerTransform::setScaleY(const qreal &scaleY)
{
    m_scaleY = scaleY;
    setContainerTransform();
}

qreal GY_ContainerTransform::containerRotation() const
{
    return m_containerRotation;
}

void GY_ContainerTransform::setContainerRotation(const qreal &containerRotation)
{
    m_containerRotation = containerRotation;
    setContainerTransform();
}

void GY_ContainerTransform::setContainerEditPointF()
{
//    setEditPointF("leftTop",QPointF(this->boundingRect().x(),this->boundingRect().y()));
//    setEditPointF("rightTop",QPointF(this->boundingRect().x()+this->boundingRect().width()
//                                   ,this->boundingRect().y()));
//    setEditPointF("leftBottom",QPointF(this->boundingRect().x()
//                                     ,this->boundingRect().y()+this->boundingRect().height()));
//    setEditPointF("rightBottom",QPointF(this->boundingRect().x() + this->boundingRect().width()
//                                        ,this->boundingRect().y() + this->boundingRect().height()));
}

void GY_ContainerTransform::setContainerTransform()
{
    QTransform form;
    if(m_isRotation){
        form.rotate(m_containerRotation);
    }
    form.scale(m_scaleX,m_scaleY);
    form.translate(m_rotationCenter.x(),m_rotationCenter.y());
    this->setTransform(form);
}

void GY_ContainerTransform::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    //!容器红色外框
//    QPen pen;
//    pen.setColor(Qt::red);
//    pen.setStyle(Qt::DotLine);
//    painter->setPen(pen);
    QGraphicsItemGroup::paint(painter,option,widget);
}

QVariant GY_ContainerTransform::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{
    //ItemPositionHasChanged
    if(change==ItemPositionChange)
    {
        //增加图形移动事件提交
        QMap<QString,GY_PropertyInfo>::Iterator iter = m_PropertyInfoMap.begin();
        while (iter != m_PropertyInfoMap.end()) {
            if((iter.value().updateType&MoveUpdate) == MoveUpdate) {
                emit this->updatePropertyEvent(this,iter.value().propertyName,
                                               this->submittingPropertyValues(iter.value().updateType,
                                                                              iter.value().propertyValue,this->getGraphicsItem()),iter.value().propertyType);
            }
            ++iter;
        }
    }
    else if(change==ItemSceneHasChanged) {
        emit itemRectChange();
    }
    return QGraphicsItemGroup::itemChange(change,value);
}
/**
 * @brief getChildrenIsContain 获取容器本身和容器下的子容器是否包含对象
 * @param guid 对象guid
 * @return  是否
 */
bool GY_ContainerTransform::getChildrenIsContain(const QString &guid)
{
    bool isContain=false;
    if(m_ChildrensMap.contains(guid))
    {
        isContain=true;
    }
    else
    {
        foreach (GY_Object* pObject, m_ChildrensMap)
        {
            if(pObject->inherits("GY_ContainerTransform"))
            {
                if(((GY_ContainerTransform*)pObject)->getIsContain(guid))
                {
                    isContain=true;
                    break;
                }
            }
        }
    }
    return isContain;
}
/**
 * @brief getIsContain 获取容器本身是否包含对象
 * @param guid 对象guid
 * @return  是否
 */
bool GY_ContainerTransform::getIsContain(const QString &guid)
{
    return m_ChildrensMap.contains(guid);
}

